/*
 * @Description: 封装常用的cesium场景效果
 * @Author: Daniel
 * @version:
 * @Date: 2023-12-18 15:03:28
 * @LastEditors: WangShuai 1830773767@qq.com
 * @LastEditTime: 2025-05-17 18:23:56
 */
import * as Cesium from "cesium";
import modifyMap from "./mapFilter";
import { update3dtilesMaxtrix, renderLightEffect,generateRandomPosition,generateCirclePoints } from "./core";
import { skyBoxData, sceneOptions } from "@/config/config.js";
import SkyBoxOnGround from "@/cesiumTools/skyBoxRepair.js";
import CustomMaterialLine from "./definedMaterial/polylineFlow";
import ConeGlow from "./definedMaterial/ConeGlow";
import FlyLineMaterial from "./definedMaterial/flyLineMaterial";
import GrandientWallMaterialProperty from "./definedMaterial/GrandientWall";
import CircleWaveMaterialProperty from "./definedMaterial/waveRing";
import {getEchartLayerOpts} from '@/staticData'
import EchartsglLayer from "./echartsLayer";
import data from '@/shader'

const {buildsFs}=data

// 天空盒配置
const skyBoxOpts = skyBoxData();

// 初始化地图场景
export const initViewer = (container) => {
  // 初始化cesium地图对象viewer
  const viewer = new Cesium.Viewer(container, {
    timeline: false, // 是否显示时间线控件
    animation: false, // 是否显示动画控件
    baseLayerPicker: false, // 避免token
    infoBox: false, // 是否显示点击要素之后显示的信息
    selectionIndicator: false, //选中元素显示,默认true
    skyAtmosphere: false, //关闭地球光环
    homeButton: false,
    fullscreenButton: false,
    geocoder: false,
    sceneModePicker: false,
    shouldAnimate: true,
    navigationHelpButton: false,
    imageryProvider: new Cesium.UrlTemplateImageryProvider({
      url: "https://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
    }),
    // terrainProvider: Cesium.createWorldTerrain({
    //   requestWaterMask: true, // 添加水面波浪效果
    //   requestVertexNormals: true, // 添加地形光照
    // }),
    // 指定上下文
    contextOptions: {
      // 支持使用老版本webgl进行着色器编写
      requestWebgl1: true,
      // 开启纹理采样异性过滤，不开的话，视角越倾斜，越模糊
      allowTextureFilterAnisotropic: true,
      webgl: {
        alpha: false,
        depth: true,
        stencil: false,
        antialias: true,
        powerPreference: "high-performance",
        premultipliedAlpha: true,
        preserveDrawingBuffer: false,
        failIfMajorPerformanceCaveat: false,
      },
    },
  });

  modifyMap(viewer, {
    //反色?
    invertColor: true,
    //滤色值
    filterRGB: [75, 75, 71],
  });
  return viewer;
};

// 设置地图场景
export const setScene = (viewer) => {
  //隐藏太阳
  viewer.scene.sun.show = false;
  //隐藏月亮
  viewer.scene.moon.show = false;
  viewer.scene.globe.enableLighting = true; // 开启全球光照

  // 泛光设置
  const bloom = viewer.scene.postProcessStages.bloom;
  bloom.enabled = false;

  // 亮度设置
  // 亮度设置
  var stages = viewer.scene.postProcessStages;
  viewer.postProcessStages.fxaa.enabled = true;
  viewer.scene.brightness =
    viewer.scene.brightness ||
    stages.add(Cesium.PostProcessStageLibrary.createBrightnessStage());
  viewer.scene.brightness.enabled = true;
  viewer.scene.brightness.uniforms.brightness = 1.2;
  viewer.scene.globe.depthTestAgainstTerrain = true;
  viewer._cesiumWidget._creditContainer.style.display = "none";

  viewer.shadows = true; //开启阴影效果
  viewer.shadowMap.darkness = 0.8; //阴影透明度--越大越透明
  //去cesium logo水印 或 css
  viewer.cesiumWidget.creditContainer.style.display = "none"; //去cesium logo水印
};

// 3dtiles模型加载
export const setTileset = (viewer, url, loadCb) => {
  // 添加白膜
  const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({ url })
  );
  // 3dtiles加载完成的回调
  tileset.readyPromise.then(() => {
    handleCityModel(tileset,viewer)
    loadCb(tileset);
  });
};

export const handleCityModel=(tileset,viewer)=>{
  tileset.style = new Cesium.Cesium3DTileStyle({
    color: {
      conditions: [["true", "color('rgba(36, 172, 242,0.9)',1)"]],
    },
  });
  // 更新3dtiles的位置，防止模型和底图位置对不上
  update3dtilesMaxtrix(0, 0, tileset);
  // 默认飞行到3dtiles的包围盒处
  const boundingSphere = tileset.boundingSphere;
  viewer.camera.flyToBoundingSphere(boundingSphere, {
    duration: 2,
    maximumHeight: 1000,
  });
}

export const loadTilesets = async (viewer, urls, cb) => {
  // 添加白膜
  const tilesets = urls.map((url) => {
    const tile = viewer.scene.primitives.add(
      new Cesium.Cesium3DTileset({ url })
    );
    return tile.readyPromise;
  });
  const result = await Promise.all(tilesets);
  console.log(result);
  cb && cb(result);
};

// 天空盒子切换
export const changeSky = (viewer, key) => {
  // 天地图配置
  const skyBoxOpts = skyBoxData();
  const target = skyBoxOpts.find((item) => item.key === key);
  if (target) {
    const groundSky = new SkyBoxOnGround({
      sources: target.sources,
    });
    viewer.scene.skyBox = groundSky;
    viewer.scene.globe.show = true;
  }
};

// 通过customshader修改模型特效
export const changeCityEffect = (value, tile) => {
  tile.customShader = null;
  // 从config的sceneOptions中找到对应的数据对象
  const target = sceneOptions.find((item) => item.label === value);
  const { fragmentShader, vetrixShader } = target;

  // 根据顶点和片元，渲染customShader
  if (fragmentShader || vetrixShader) {
    renderLightEffect(vetrixShader, fragmentShader, tile);
  } else {
    tile.customShader = null;
  }
};

// 加载道路线
let dataS;
export const loadLines = async (viewer, url, isFlow) => {
  const promise = Cesium.GeoJsonDataSource.load(url);
  const dataSource = await promise;
  dataS = dataSource;
  console.log(dataSource);
  viewer.dataSources.add(dataSource);
  // 获取到加载的实体entities
  const roadEnts = dataSource.entities.values;
  let material;
  if (isFlow) {
    material = new CustomMaterialLine({
      image: "/src/assets/line.png",
      duration: 1000,
      color: Cesium.Color.ORANGE,
      repeat: 33,
    });
  } else {
    material = new Cesium.PolylineGlowMaterialProperty({
      //设置Glow材质
      glowPower: 0.12,
      color: Cesium.Color.ORANGERED.withAlpha(0.9),
    });
  }

  roadEnts.forEach((roadEnt) => {
    roadEnt.polyline.clampToGround = true;
    roadEnt.polyline.material = material;
    roadEnt.polyline.width = isFlow ? 3 : 12;
  });

  return roadEnts;
};

export const removeLines = (viewer) => {
  dataS && viewer.dataSources.remove(dataS);
  dataS = null;
};

let currentClimate
export const climateChange = (obj,viewer) => {
  closeClimate(viewer)
  if (obj) {
    const { label, fs } = obj;
    currentClimate=label
    const climate = new Cesium.PostProcessStage({
      name: label,
      // 相关着色器
      fragmentShader: fs,
      uniforms: {
        // rainSize代表雨水的密集程度
        rainSize: () => {
          return 3.4;
        },
        // 降雨速度
        rainSpeed: () => {
          return 100.0;
        },
      },
    });
    viewer.scene.postProcessStages.add(climate);
  }
};

export const closeClimate = (viewer) => {
  const target = viewer.scene.postProcessStages.getStageByName(currentClimate);
  if (target) {
    viewer.scene.postProcessStages.remove(target);
    currentClimate = null;
  }
};

// 飞行到模型处
export const flyToTile = (viewer, tileset) => {
  // 默认飞行到3dtiles的包围盒处
  const boundingSphere = tileset.boundingSphere;
  viewer.camera.flyToBoundingSphere(boundingSphere, {
    duration: 2,
    maximumHeight: 1000,
  });
};

// 处理倾斜摄影
export const handleBuilds = (tileset) => {
  const customShader = new Cesium.CustomShader({
    uniforms: {
      u_snowAlpha: {
        type: Cesium.UniformType.FLOAT,
        value: 0,
      },
      u_rainAlpha: {
        type: Cesium.UniformType.FLOAT,
        value: 0,
      },
    },
    fragmentShaderText: buildsFs,
  });
  tileset.customShader = customShader;
};


/**
 * @description:
 * @param {{lng,lat}} center
 * @param {Number} count
 * @param {Number} spreadHeight
 * @param {Number} speed
 * @param {Cesium.Color} lineColor
 * @return {*}
 */
 let spreadLines = [];
 export const addFlyLines = (
   center,
   count,
   spreadHeight,
   speed,
   lineColor,
   viewer
 ) => {
   center = Cesium.defaultValue(center, {});
   count = Cesium.defaultValue(count, 300);
   spreadHeight = Cesium.defaultValue(spreadHeight, 6000);
   speed = Cesium.defaultValue(speed, 20);
   lineColor = Cesium.defaultValue(
     lineColor,
     new Cesium.Color(1.0, 1.0, 0.0, 0.8)
   );
   const positions = generateRandomPosition(center, count, 0.08);
   const lines = [];
   positions.forEach((item) => {
     // 经纬度
     let start_lon = item[0];
     let start_lat = item[1];
 
     let startPoint = new Cesium.Cartesian3.fromDegrees(start_lon, start_lat, 0);
 
     // 随机高度
     let height = 5000 * Math.random();
     let endPoint = new Cesium.Cartesian3.fromDegrees(
       start_lon,
       start_lat,
       height
     );
     let linePositions = [];
     linePositions.push(startPoint);
     linePositions.push(endPoint);
     const ent = viewer.entities.add({
       polyline: {
         positions: linePositions,
         material: new FlyLineMaterial({
           color: lineColor,
           speed: speed * Math.random(),
           percent: 0.1
         }),
       },
     });
     lines.push(ent);
   });
   spreadLines = lines;
   return lines;
 };
 
 // 去除飞线效果
 export const removeFlyLines = (viewer) => {
   if (spreadLines.length) {
     spreadLines.forEach((item) => {
       viewer.entities.remove(item);
     });
     spreadLines = [];
   }
 };

/**
 * @description: 添加光锥柱体
 * @param {Cesium.Cartesian3} position
 * @param {Number} height
 * @param {Number} bottomRadius
 * @param {Cesium.Color} color
 * @return {*}
 */
 let coneGlows = [];
 export const addConeGlow = (position, height, bottomRadius, color, viewer) => {
   position = Cesium.defaultValue(position, {});
   height = Cesium.defaultValue(height, 3000);
   bottomRadius = Cesium.defaultValue(bottomRadius, 150);
   color = Cesium.defaultValue(color, Cesium.Color.AQUA);
   const coneGlowContoller = new ConeGlow(viewer, position, {});
   console.log(coneGlowContoller);
   coneGlowContoller.addEnt();
 };

//  添加标志性建筑
 export const addMarkBuild=(position,viewer)=>{
  // 构造modelMatrix
  const {lng,lat,height}=position
  const positionCar3=Cesium.Cartesian3.fromDegrees(lng,lat,height)
  const modelMatrix=Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(positionCar3),
  new Cesium.Cartesian3(0,0,0),new Cesium.Matrix4())

  const model=Cesium.Model.fromGltf({
    url:'/src/assets/build.gltf',
    modelMatrix,
    customShader:new Cesium.CustomShader({
      uniforms:{
        u_texture:{
          value:new Cesium.TextureUniform({
            url:'/src/assets/color2.png'
          }),
          type:Cesium.UniformType.SAMPLER_2D
        }
      },
      fragmentShaderText:/*glsl*/`
        void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material){
          vec2 uv=fsInput.attributes.texCoord_0;
          float ITime=czm_frameNumber/120.0;
          ITime=fract(ITime);
          vec4 textureColor=texture2D(u_texture,vec2(uv.x,uv.y+ITime));
          material.diffuse=textureColor.rgb*1.6;
        }
      `
    })
  })
  viewer.scene.primitives.add(model)
 }

//  添加电子围栏
// option Array<{wallHeight,wallColor}>
// wallHeight Number
// wallColor Cesium.Color
// position {lng,lat}
export const addFence=(position,option,viewer)=>{
    position=Cesium.defaultValue(position,{})
    const {lng,lat}=position
    // 墙的高度
    let wallHeight=option.wallHeight || 1000
    let wallColor=option.wallColor || Cesium.Color.RED
    let wallRadius=option.wallRadius || 500
    // 墙的最低高度
    let wallMinHeight=option.wallMinHeight || 400
    const wallPositions=generateCirclePoints([lng,lat],wallRadius)
    console.log(wallPositions);

    let minimumHeights=[]
    let maximumHeights=[]
    let positionsCar3=[]
    wallPositions.map(item=>{
      minimumHeights.push(wallMinHeight)
      maximumHeights.push(wallMinHeight+wallHeight)
      positionsCar3.push(...item,wallMinHeight)
    })
    // 转化坐标
    positionsCar3=new Cesium.Cartesian3.fromDegreesArrayHeights(positionsCar3)
    console.log(positionsCar3);
    console.log(minimumHeights);
    console.log(maximumHeights);
    const fence= viewer.entities.add({
      wall:{
        positions:positionsCar3,
        minimumHeights,
        maximumHeights,
        material:new GrandientWallMaterialProperty(wallColor)
      }
    })
    return fence
 }

//  添加扩散波纹圆
// position {lng,lat,height}
export const addWaveRing=(position,radius,color,viewer)=>{
  position=Cesium.defaultValue(position,{})
  radius=Cesium.defaultValue(radius,500)
  color=Cesium.defaultValue(color,Cesium.Color.ORANGE)

  const {lng,lat,height}=position
  const positionCar3=Cesium.Cartesian3.fromDegrees(lng,lat,height)
  let duration=1000
  const moveRing=viewer.entities.add({
    position:positionCar3,
    ellipse: {
      semiMinorAxis: radius,
      semiMajorAxis: radius,
      height: height,
      material: new CircleWaveMaterialProperty({
        duration,
        color,
        count:3
      })
    }
  })
  return moveRing
}

// 添加echarts图层
export const addEchartsLayer=(viewer,echartsPoints)=>{
  const echartsLayer=new EchartsglLayer(viewer)
  const options=getEchartLayerOpts(echartsPoints)
  echartsLayer.init(options)
  return ()=>{
    echartsLayer.remove()
  }
}

